package 单例模式.懒汉式;


/**
 * 懒汉式 就是在调用getInstance的时候创建对象
 * 在调用方法时通常要进行对象是否存在的判断 因此线程不安全
 */
public class Singleton {
    public static void main(String[] args) {
        //创建30个线程验证 线程安全
        for (int i = 0; i < 30; i++) {
            new Thread(() -> {
                Singleton1 s = Singleton1.getInstance();
                System.out.println(s.hashCode());
            }).start();
        }
    }
}

/**
 * 线程不安全
 */
class Singleton1 {
    private static Singleton1 instance;

    private Singleton1() {

    }

    public static Singleton1 getInstance() {
        if (instance == null) {
            instance = new Singleton1();
        }
        return instance;
    }
}

/**
 * 线程安全
 * 方法级别同步代码
 * 缺点每次调用getInstance()都要排队，效率低
 */
class Singleton2 {
    private static Singleton2 instance;

    private Singleton2() {

    }

    public static synchronized Singleton2 getInstance() {
        if (instance == null) {
            instance = new Singleton2();
        }
        return instance;
    }
}

/**
 * 双重检查 线程安全 推荐使用
 */
class Singleton3 {
    private static volatile Singleton3 instance;

    private Singleton3() {

    }

    public static Singleton3 getInstance() {
        if (instance == null) {
            //如果AB两个线程同时进入了if判断内部，则排队进入同步代码块
            //A线程进入后 创建了对象
            //B进入同步代码块后则不会创建对象
            synchronized (Singleton3.class) {
                if (instance == null) {
                    instance = new Singleton3();
                }
            }
        }
        return instance;
    }
}
